package com.rgst.serivce.impl;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.transaction.Transactional;

import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import com.rgst.dao.entity.Busi;
import com.rgst.dao.entity.Enroll;
import com.rgst.dao.entity.EnrollExtFields;
import com.rgst.dao.entity.Student;
import com.rgst.dao.entity.User;
import com.rgst.dao.repository.EnrollExtFieldsRepository;
import com.rgst.dao.repository.EnrollRepository;
import com.rgst.dao.repository.StudentRepository;
import com.rgst.dto.Result;
import com.rgst.serivce.EnrollService;
import com.rgst.utils.DateUtil;
import com.rgst.utils.ExportUtil;

/**
 * Created by tancw on 2019/11/24.
 */
@Service
public class EnrollServiceImpl implements EnrollService {

    @Autowired
    private StudentRepository studentRepository;
    @Autowired
    private EnrollRepository enrollRepository;
    @Autowired
    private EnrollExtFieldsRepository enrollExtFieldsRepository;

    @Override
    @Transactional
    public Result submit(Student student, Enroll enroll) {
        try {
            Assert.isTrue((student.getRealname() != null
                    && student.getRealname() != ""), "学生姓名不能为空");
            Assert.notNull(student.getSex(), "学生姓别不能为空");
            Student stuRet = studentRepository.save(student);
            enroll.setStuId(stuRet.getId());
            enroll.setCreateTime(new Date());
            Enroll enrollRet = enrollRepository.save(enroll);

            if(!CollectionUtils.isEmpty(enroll.getEnrollExtFields())) {
                enrollExtFieldsRepository.saveAll(enroll.getEnrollExtFields());
            }

            return Result.success(enrollRet);
        } catch (Exception e) {
            e.printStackTrace();
            return Result.error(e.getMessage());
        }
    }

    @Override
    public List<Enroll> query(Long userId) {
        return enrollRepository.findAllByUserId(userId);
    }

    @Override
    public Page<Enroll> listData(Map param, Pageable pageable) {
        Specification specification = new Specification() {
            @Override
            public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder cb) {
                List<Predicate> predicatesList = new ArrayList<>();

                predicatesList.add(cb.equal(root.get("state"), 1));

                String sdateStr = MapUtils.getString(param, "sdate");
                String edateStr = MapUtils.getString(param, "edate");
                if (sdateStr != null && edateStr != null) {
                    Date sdate = DateUtil.parse(sdateStr);
                    Date edate = DateUtils.addSeconds(DateUtil.parse(edateStr), 86399);
                    predicatesList.add(cb.between(root.get("createTime"), sdate, edate));
                }

                Long busiId = MapUtils.getLong(param, "busiId");
                if (busiId != null) {
                    predicatesList.add(cb.equal(root.get("busiId"), busiId));
                }

                String dep = MapUtils.getString(param, "dep");
                if (StringUtils.isNotBlank(dep)) {
                    predicatesList.add(cb.equal(root.get("dep"), dep));
                }

                String grade = MapUtils.getString(param, "grade");
                if (StringUtils.isNotBlank(grade)) {
                    predicatesList.add(cb.equal(root.get("grade"), grade));
                }

                String className = MapUtils.getString(param, "className");
                if (StringUtils.isNotBlank(className)) {
                    predicatesList.add(cb.equal(root.get("className"), className));
                }

                String uname = MapUtils.getString(param, "Urealname");
                if (StringUtils.isNotBlank(uname)) {
                    predicatesList.add(cb.like(root.get("uname"), "%" + uname + "%"));
                }
                String sname = MapUtils.getString(param, "Srealname");
                if (StringUtils.isNotBlank(sname)) {
                    predicatesList.add(cb.like(root.get("sname"), "%" + sname + "%"));
                }
                Predicate[] predicates = new Predicate[predicatesList.size()];
                return cb.and(predicatesList.toArray(predicates));
            }
        };

        Page<Enroll> enrolls = enrollRepository.findAll(specification, pageable);
        return enrolls;
    }

    @Override
    public Workbook getForExcel(Map<String, Object> param, Pageable pageable) {
        Page<Enroll> enrolls = listData(param, pageable);
        if (enrolls.isEmpty()) return null;
        List<String> head = initHead();
        List<List<String>> content = new ArrayList<>();
        for (Enroll enroll : enrolls.getContent()) {
            List<String> item = initItem(head, enroll);
            content.add(item);
        }
        return ExportUtil.getExcelWork("报名信息", head.toArray(new String[head.size()]), content);
    }

    private List<String> initItem(List<String> head, Enroll enroll) {
        List<String> item = new ArrayList<>();
        Busi busi = enroll.getBusi();
        User user = enroll.getUser();
        Student student = enroll.getStudent();
        List<EnrollExtFields> exs = enroll.getEnrollExtFields();

        item.add(busi.getTitle());
        item.add(user.getRealname());
        item.add(user.getMobile());
        item.add(student.getRealname());
        item.add(student.getSexDict());
        item.add(enroll.getDep());
        item.add(enroll.getGrade());
        item.add(enroll.getClassName());
        item.add(DateUtil.format(enroll.getCreateTime(), DateUtil.DEFAULT_DAYTIME_FORMAT));
        initExtFields(exs, head, item);
        return item;
    }

    private void initExtFields(List<EnrollExtFields> exs, List<String> head, List<String> item) {
        if (CollectionUtils.isEmpty(exs)) return;
        for (EnrollExtFields extFields : exs) {
            String extHead = "【" + extFields.getTitle() + "】";
            int index = getIndex(head, extHead);

            itemSet(item, index, extFields.getValue());
        }
    }

    private void itemSet(List<String> item, int index, String value) {
        int len = item.size();
        do {
            item.add("");
            len = item.size();
            if (len > 100) {
                throw new IllegalArgumentException("Error ext fields");
            }
        } while (len <= index);
        item.set(index, value);
    }

    private int getIndex(List<String> head, String extHead) {
        int index = -1;
        if (head.contains(extHead)) {
            for (int j = 0, len = head.size(); j < len; j++) {
                String oldHead = head.get(j);
                if (StringUtils.equals(oldHead, extHead)) {
                    return j;
                }
            }
        } else {
            index = head.size();
            head.add(extHead);
        }
        return index;
    }

    private List<String> initHead() {
        List head = new ArrayList();
        Collections.addAll(head,
                "项目名称",
                "家长姓名",
                "家长电话",
                "学生姓名",
                "学生性别",
                "学部",
                "年级",
                "班级",
                "报名时间");
        return head;
    }
}
